#pragma once
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include "Log.hpp"
#include "Mutex.hpp"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <strings.h>
#include <functional>

using namespace LogModule;
using func_t = std::function<std::string(const std::string &)>;
const int default_fd = -1;
class UDPServer
{
public:
    UDPServer(uint16_t port, func_t funC)
        : _socket_fd(default_fd), _port(port), _is_running(false), _fun(funC) {}
    void init()
    {
        // 创建套接字
        _socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_socket_fd < 0)
        {
            LOG(LogLevel::FATAL) << "Failed to create socket";
            exit(EXIT_FAILURE);
        }
        LOG(LogLevel::INFO) << "Socket created with fd: " << _socket_fd;
        // 绑定地址信息
        //(1) 填充socketaddr_in 结构体

        struct sockaddr_in server_addr;
        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_port = htons(_port); // 本地序列转换成网络序列
        // server_addr.sin_addr.s_addr = inet_addr(_ip.c_str()); // ip地址转换 成网络序列
        server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡
        server_addr.sin_family = AF_INET;
        //(2) bind
        int n = bind(_socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "Failed to bind socket";
            exit(2);
        }
        LOG(LogLevel::INFO) << "Socket binded with " << ":" << _port << "success!!!";
    }
    void start()
    {
        _is_running = true;
        while (_is_running)
        {
            // 收取消息
            //(1) recvfrom
            char buffer[1024];
            struct sockaddr_in client_addr;
            socklen_t client_addr_len = sizeof(client_addr);

            ssize_t recv_len = recvfrom(_socket_fd, buffer, sizeof(buffer) - 1, 0,
                                        (struct sockaddr *)&client_addr, &client_addr_len);
            if (recv_len > 0)
            {

                buffer[recv_len] = '\0'; // 添加字符串结束符
                //InetAddr inet_addr(client_addr);

                std::string result = _fun(buffer);

                //(2) 处理数据  这里简单打印
                std::string client_ip = inet_ntoa(client_addr.sin_addr);
                uint16_t client_port = ntohs(client_addr.sin_port);

                LOG(LogLevel::INFO) << "Received " << recv_len
                << " bytes from "
                << client_ip << ":" << client_port
                << " Data: " << buffer;

                //(3) sendto
                // std::string response = "Message received";
                // response += buffer; // 回显收到的消息
                // ssize_t sent_len = sendto(_socket_fd, response.c_str(), response.size(), 0,
                //                           (struct sockaddr *)&client_addr, client_addr_len);

                ssize_t sent_len = sendto(_socket_fd, result.c_str(), result.size(), 0,
                                          (struct sockaddr *)&client_addr, client_addr_len);
            }
        }
    }
    ~UDPServer() {}

private:
    int _socket_fd;
    uint16_t _port;
    func_t _fun;
    bool _is_running;
};
